package org.xx.armory.spring5.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import javax.servlet.http.HttpServletRequest;
import java.text.Collator;

import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.xx.armory.commons.Converter.toStr;
import static org.xx.armory.commons.StringConverter.parseInteger;

/**
 * 用于验证身份的数据。
 *
 * <p>和 {@link  WebAuthenticationDetails} 相比，额外包含了验证码是否匹配和登录渠道。</p>
 */
public class ArmoryWebAuthenticationDetails
        extends WebAuthenticationDetails {
    private static final long serialVersionUID = 1L;
    /**
     * 在Session中保存验证码的属性名。
     */
    private static final String CAPTCHA_CODE_KEY = "__captcha_code__";

    private static final Collator TEXT_COLLATOR = createTextCollator();

    private final Logger logger = LoggerFactory.getLogger(ArmoryWebAuthenticationDetails.class);
    private final boolean captchaCodeMatched;
    private final int channel;

    public ArmoryWebAuthenticationDetails(
            HttpServletRequest request
    ) {
        super(request);

        final var expectedCaptchaCode = trimToEmpty(toStr(request.getSession().getAttribute(CAPTCHA_CODE_KEY)));
        if (expectedCaptchaCode.isEmpty()) {
            this.captchaCodeMatched = true;
        } else {
            final var captchaCode = trimToEmpty(request.getParameter("captchaCode"));
            this.captchaCodeMatched = TEXT_COLLATOR.equals(expectedCaptchaCode, captchaCode);
        }

        if (this.captchaCodeMatched) {
            // 如果验证通过，那么从Session中删除验证码。
            logger.trace("Clear captcha-code after successful checking");
            request.getSession().removeAttribute(CAPTCHA_CODE_KEY);
        }

        this.channel = parseInteger(request.getParameter("channel"), 1);
    }

    private static Collator createTextCollator() {
        final var result = Collator.getInstance();

        result.setStrength(Collator.PRIMARY);

        return result;
    }

    /**
     * 判断用户输入的验证码是否匹配。
     *
     * @return 用户输入的验证码是否匹配。
     */
    public boolean isCaptchaCodeMatched() {
        return this.captchaCodeMatched;
    }

    /**
     * 获取用户登录的渠道。
     *
     * @return 用户登录的渠道。
     */
    public int getChannel() {
        return this.channel;
    }

    @Override
    public String toString() {
        return "ArmoryWebAuthenticationDetails("
                + "captchaCodeMatched=" + this.captchaCodeMatched + ","
                + "channel=" + this.channel
                + ")";
    }
}
